{
  "name": "Case 68 - Car Dealership Sales & Service Monitor",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "triggerAtDay": [
                1
              ],
              "triggerAtHour": 9
            }
          ]
        }
      },
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        -800,
        -96
      ],
      "id": "fa1b74d9-fe71-451c-8c9c-87c96c61dbfa",
      "name": "Weekly Schedule - Monday 9 AM"
    },
    {
      "parameters": {
        "actorId": {
          "__rl": true,
          "value": "Xb8osYTtOjlsgI6k9",
          "mode": "id",
          "cachedResultName": "Google Maps Scraper"
        },
        "customBody": "={\n  \"language\": \"en\",\n  \"maxReviews\": 100,\n  \"personalData\": true,\n  \"startUrls\": [\n    {\n      \"url\": \"https://www.google.com/maps/place/Toyota+of+Manhattan/@40.7650868,-73.9980392,17z/data=!3m2!4b1!5s0x89c2584fc56e21f1:0x7a7ce4eb08029d8e!4m6!3m5!1s0x89c2584e35576ebd:0xab24f81e5b166953!8m2!3d40.7650828!4d-73.9954643!16s%2Fg%2F1tpf80v7?entry=ttu&g_ep=EgoyMDI1MTIwOS4wIKXMDSoASAFQAw%3D%3D\"\n    }\n  ],\n  \"reviewsSort\": \"newest\",\n  \"reviewsOrigin\": \"all\"\n}"
      },
      "type": "@apify/n8n-nodes-apify.apify",
      "typeVersion": 1,
      "position": [
        -624,
        -96
      ],
      "id": "fb20d62b-52e6-46e6-8a71-0ebde4d384fe",
      "name": "Scrape Dealership Reviews",
      "credentials": {
        "apifyApi": {
          "id": "w5S6YBbbyUddEfQA",
          "name": "Apify account"
        }
      }
    },
    {
      "parameters": {
        "resource": "Datasets",
        "datasetId": "={{ $json.defaultDatasetId }}",
        "limit": 100
      },
      "type": "@apify/n8n-nodes-apify.apify",
      "typeVersion": 1,
      "position": [
        -432,
        -96
      ],
      "id": "9cda998f-34b9-4dba-a337-b57ed9939b5f",
      "name": "Get Dataset Items",
      "credentials": {
        "apifyApi": {
          "id": "w5S6YBbbyUddEfQA",
          "name": "Apify account"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "filter-1star",
              "leftValue": "={{ $json.stars }}",
              "rightValue": 1,
              "operator": {
                "type": "number",
                "operation": "equals"
              }
            },
            {
              "id": "filter-2star",
              "leftValue": "={{ $json.stars }}",
              "rightValue": 2,
              "operator": {
                "type": "number",
                "operation": "equals"
              }
            }
          ],
          "combinator": "or"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2,
      "position": [
        -240,
        -96
      ],
      "id": "a4c15435-a441-495f-9f91-e0d02c71715f",
      "name": "Filter 1-2 Star Reviews"
    },
    {
      "parameters": {
        "modelId": {
          "__rl": true,
          "value": "gpt-4o",
          "mode": "list",
          "cachedResultName": "GPT-4o"
        },
        "responses": {
          "values": [
            {
              "role": "system",
              "content": "You are an Automotive Dealership Analyst. Read the review carefully and categorize it.\n\nReturn ONLY this JSON format:\n{\n  \"complaint_category\": \"Sales Pressure|Service Wait Time|Repair Quality|Pricing Transparency|Staff Professionalism|Facility Cleanliness|Other\",\n  \"severity\": \"critical|high|medium|low\",\n  \"emotional_tone\": \"Angry|Frustrated|Disappointed|Calm|Sarcastic\",\n  \"specific_issue\": \"what went wrong\",\n  \"key_quote\": \"most important sentence from review\"\n}\n\nHOW TO CATEGORIZE:\n\nSales Pressure = Aggressive tactics, pressure to buy, dishonesty\nKeywords: pushy, aggressive, lied, deceived, pressure tactics, bait and switch\nExample: \"Salesperson was extremely pushy\" → Sales Pressure\n\nService Wait Time = Long waits for service/repairs\nKeywords: waited hours, took forever, slow service, no loaner car\nExample: \"Waited 4 hours for oil change\" → Service Wait Time\n\nRepair Quality = Poor repairs, problem returned, damage caused\nKeywords: didn't fix, still broken, made worse, damaged car, shoddy work\nExample: \"Problem came back after repair\" → Repair Quality\n\nPricing Transparency = Hidden fees, overcharged, pricing issues\nKeywords: hidden fees, overcharged, bait and switch, surprise charges, markup\nExample: \"Charged $500 more than quoted\" → Pricing Transparency\n\nStaff Professionalism = Rude, unprofessional, disrespectful behavior\nKeywords: rude, unprofessional, disrespectful, condescending, dismissive\nExample: \"Service advisor was condescending\" → Staff Professionalism\n\nFacility Cleanliness = Dirty waiting area, bathrooms, service bays\nKeywords: dirty, filthy, gross facilities, messy showroom\nExample: \"Waiting room was disgusting\" → Facility Cleanliness\n\nOther = Everything else\nExample: \"Parking lot was too small\" → Other\n\nSEVERITY RULES:\n- critical: Safety issues (brakes not fixed, dangerous repairs), fraud, theft\n- high: Major service failures, very angry customer, expensive mistakes\n- medium: Frustrating experience, poor service, minor repair issues\n- low: Minor inconveniences, constructive feedback\n\nEMOTIONAL TONE RULES:\n- Angry: Profanity, threats, extreme anger, \"never coming back\"\n- Frustrated: Multiple complaints, \"disappointed\", \"waste of time\"\n- Disappointed: Unmet expectations, sad tone, \"expected better\"\n- Calm: Neutral feedback, no strong emotion\n- Sarcastic: Mockery, ironic comments, passive-aggressive\n\nReturn ONLY the JSON. No explanation."
            },
            {
              "content": "=Analyze this dealership review:\n\nDealership: {{ $json.title }}\nCustomer: {{ $json.name }}\nRating: {{ $json.stars }} stars\nDate: {{ $json.publishedAtDate }}\nReview Text: {{ $json.text }}\n\nReturn only JSON."
            }
          ]
        },
        "builtInTools": {},
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 2.1,
      "position": [
        -48,
        -96
      ],
      "id": "2db88da7-44fa-4258-96b1-b122d8231bbc",
      "name": "AI: Analyze Review",
      "credentials": {
        "openAiApi": {
          "id": "ICwxUBbatsF2sDvy",
          "name": "OpenAi account"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// STANDARD AI RESPONSE PARSER\n// Use this after every AI node to convert text into drag-droppable fields\n// Students: You don't need to understand this code - just connect it after AI nodes!\n\nconst items = [];\nconst input = $input.all();\n\ninput.forEach((item, index) => {\n  try {\n    // Get AI response text\n    const aiText = item.json.output[0].content[0].text;\n    \n    // Clean markdown code blocks if present\n    const cleaned = aiText.replace(/```json\\n?/g, '').replace(/```\\n?/g, '').trim();\n    \n    // Parse JSON string into object\n    const parsed = JSON.parse(cleaned);\n    \n    // Return parsed fields (now you can drag-drop these!)\n    items.push({\n      json: parsed\n    });\n  } catch (error) {\n    console.error(`Error parsing AI response for item ${index}:`, error.message);\n    // Return empty fields if parsing fails\n    items.push({\n      json: {\n        error: `Parse failed: ${error.message}`\n      }\n    });\n  }\n});\n\nreturn items;\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        224,
        -96
      ],
      "id": "fcbfdd20-7172-414d-86fa-919446477acf",
      "name": "Parse AI Response"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "cat",
              "name": "complaint_category",
              "value": "={{ $json.complaint_category }}",
              "type": "string"
            },
            {
              "id": "sev",
              "name": "severity",
              "value": "={{ $json.severity }}",
              "type": "string"
            },
            {
              "id": "tone",
              "name": "emotional_tone",
              "value": "={{ $json.emotional_tone }}",
              "type": "string"
            },
            {
              "id": "issue",
              "name": "specific_issue",
              "value": "={{ $json.specific_issue }}",
              "type": "string"
            },
            {
              "id": "quote",
              "name": "key_quote",
              "value": "={{ $json.key_quote }}",
              "type": "string"
            },
            {
              "id": "date",
              "name": "review_date",
              "value": "={{ $('Filter 1-2 Star Reviews').item.json.publishedAtDate }}",
              "type": "string"
            },
            {
              "id": "reviewer",
              "name": "customer_name",
              "value": "={{ $('Filter 1-2 Star Reviews').item.json.name }}",
              "type": "string"
            },
            {
              "id": "rating",
              "name": "star_rating",
              "value": "={{ $('Filter 1-2 Star Reviews').item.json.stars }}",
              "type": "number"
            },
            {
              "id": "text",
              "name": "review_text",
              "value": "={{ $('Filter 1-2 Star Reviews').item.json.textTranslated || $('Filter 1-2 Star Reviews').item.json.text }}",
              "type": "string"
            },
            {
              "id": "url",
              "name": "review_url",
              "value": "={{ $('Filter 1-2 Star Reviews').item.json.reviewUrl }}",
              "type": "string"
            },
            {
              "id": "loc",
              "name": "dealership_name",
              "value": "={{ $('Filter 1-2 Star Reviews').item.json.title }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        384,
        -96
      ],
      "id": "0eb85376-ef1d-46e7-8417-e5e1cd4bf3b1",
      "name": "Edit Fields"
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "1JzAkwVSe7TUcuh2uESWt-O4Jqhee9dB8jrtbXoPgm0k",
          "mode": "list",
          "cachedResultName": "Case 68 - Car Dealership Sales and Service Log",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1JzAkwVSe7TUcuh2uESWt-O4Jqhee9dB8jrtbXoPgm0k/edit?usp=drivesdk"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "Sheet1",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1JzAkwVSe7TUcuh2uESWt-O4Jqhee9dB8jrtbXoPgm0k/edit#gid=0"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Review_Date": "={{ $json.review_date }}",
            "Customer_Name": "={{ $json.customer_name }}",
            "Star_Rating": "={{ $json.star_rating }}",
            "Review_Text": "={{ $json.review_text }}",
            "Complaint_Category": "={{ $json.complaint_category }}",
            "Severity": "={{ $json.severity }}",
            "Emotional_Tone": "={{ $json.emotional_tone }}",
            "Specific_Issue": "={{ $json.specific_issue }}",
            "Key_Quote": "={{ $json.key_quote }}",
            "Review_URL": "={{ $json.review_url }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "Review_Date",
              "displayName": "Review_Date",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Customer_Name",
              "displayName": "Customer_Name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Star_Rating",
              "displayName": "Star_Rating",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Review_Text",
              "displayName": "Review_Text",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Complaint_Category",
              "displayName": "Complaint_Category",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Severity",
              "displayName": "Severity",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Emotional_Tone",
              "displayName": "Emotional_Tone",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Specific_Issue",
              "displayName": "Specific_Issue",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Key_Quote",
              "displayName": "Key_Quote",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Review_URL",
              "displayName": "Review_URL",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        544,
        -96
      ],
      "id": "7bc3c7fa-d623-4455-b4c6-8dcabab9a425",
      "name": "Log to Google Sheet",
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "LOs2dbk9lby0NfDM",
          "name": "Google Sheets account"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const items = $('Edit Fields').all();\n\nif (items.length === 0) {\n  return [{ json: { total_negative_reviews: 0, category_breakdown: {}, severity_breakdown: {}, emotional_tone_breakdown: {}, top_issues: [], dealership_name: 'Unknown' } }];\n}\n\nconst categoryCount = {};\nconst severityCount = {};\nconst emotionalToneCount = {};\nconst allIssues = [];\nconst dealership_name = items[0].json.dealership_name || 'Unknown';\n\nitems.forEach(item => {\n  const data = item.json;\n  const category = data.complaint_category || 'Other';\n  categoryCount[category] = (categoryCount[category] || 0) + 1;\n  const severity = data.severity || 'low';\n  severityCount[severity] = (severityCount[severity] || 0) + 1;\n  const tone = data.emotional_tone || 'Calm';\n  emotionalToneCount[tone] = (emotionalToneCount[tone] || 0) + 1;\n  \n  allIssues.push({\n    issue: data.specific_issue || '',\n    quote: data.key_quote || '',\n    customer: data.customer_name || 'Anonymous',\n    date: data.review_date || '',\n    rating: data.star_rating || 0,\n    url: data.review_url || '',\n    severity: data.severity || 'low',\n    category: data.complaint_category || 'Other'\n  });\n});\n\nconst severityOrder = { critical: 4, high: 3, medium: 2, low: 1 };\nallIssues.sort((a, b) => (severityOrder[b.severity] || 0) - (severityOrder[a.severity] || 0));\nconst topIssues = allIssues.slice(0, 5);\n\nreturn [{ json: { total_negative_reviews: items.length, category_breakdown: categoryCount, severity_breakdown: severityCount, emotional_tone_breakdown: emotionalToneCount, top_issues: topIssues, dealership_name: dealership_name } }];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        720,
        -96
      ],
      "id": "414c2cfe-c8a0-458a-9ef7-ce79716d81ff",
      "name": "Aggregate Summary"
    },
    {
      "parameters": {
        "sendTo": "gm@dealership.com",
        "subject": "=Weekly Service & Sales Report - {{ $json.dealership_name }}",
        "message": "=<html><head><style>body{font-family:Arial,sans-serif;line-height:1.6;color:#333;background:#f5f5f5;margin:0;padding:0}.container{max-width:700px;margin:20px auto;background:white;border-radius:10px;overflow:hidden;box-shadow:0 4px 20px rgba(0,0,0,0.15)}.header{background:linear-gradient(135deg,#1e40af 0%,#1e3a8a 100%);color:white;padding:30px;text-align:center}.header h1{margin:0 0 10px 0;font-size:26px}.content{padding:30px}.stats-section{margin:25px 0}.stats-section h3{color:#1e40af;border-bottom:2px solid #1e40af;padding-bottom:10px;margin-bottom:15px}.stat-grid{display:grid;grid-template-columns:1fr 1fr;gap:15px}.stat-box{background:#f8f9fa;padding:15px;border-radius:8px;text-align:center;border:1px solid #dee2e6}.stat-number{font-size:28px;font-weight:bold;color:#dc2626;margin:0}.breakdown-item{background:#f8f9fa;padding:12px 15px;margin:8px 0;border-radius:5px;display:flex;justify-content:space-between}.breakdown-count{background:#1e40af;color:white;padding:4px 12px;border-radius:15px;font-weight:bold}.issue-card{background:#dbeafe;padding:15px;margin:12px 0;border-radius:8px;border-left:4px solid #1e40af}.recommendations{background:#dcfce7;padding:20px;margin:25px 0;border-radius:8px;border:2px solid #16a34a}.footer{background:#f5f5f5;padding:20px;text-align:center;color:#666;font-size:12px}</style></head><body><div class=\"container\"><div class=\"header\"><h1>🚗 Weekly Dealership Report</h1><div>{{ $json.dealership_name }}</div></div><div class=\"content\"><div class=\"stats-section\"><h3>Overview</h3><div class=\"stat-grid\"><div class=\"stat-box\"><div class=\"stat-number\">{{ $json.total_negative_reviews }}</div><div>Negative Reviews</div></div><div class=\"stat-box\"><div class=\"stat-number\">{{ Object.keys($json.category_breakdown).length }}</div><div>Issue Categories</div></div></div></div><div class=\"stats-section\"><h3>Complaint Categories</h3>{{ Object.keys($json.category_breakdown).map(cat => `<div class=\"breakdown-item\"><span>${cat}</span><span class=\"breakdown-count\">${$json.category_breakdown[cat]}</span></div>`).join('') }}</div><div class=\"stats-section\"><h3>Severity Breakdown</h3>{{ Object.keys($json.severity_breakdown).map(sev => `<div class=\"breakdown-item\"><span>${sev.charAt(0).toUpperCase() + sev.slice(1)}</span><span class=\"breakdown-count\">${$json.severity_breakdown[sev]}</span></div>`).join('') }}</div><div class=\"stats-section\"><h3>Top Priority Issues</h3>{{ $json.top_issues.map(issue => `<div class=\"issue-card\"><div><strong>${issue.category}</strong> - ${issue.severity.toUpperCase()}</div><div>${issue.issue}</div><div>\"${issue.quote}\"</div><div>— ${issue.customer} | ⭐${issue.rating}/5</div><a href=\"${issue.url}\" style=\"color:#1e40af;text-decoration:none;\">→ View Review</a></div>`).join('') }}</div><div class=\"recommendations\"><h3>Recommended Actions</h3><ul><li>Address critical safety issues immediately</li><li>Review sales training if Sales Pressure is top category</li><li>Audit service department wait times and staffing</li><li>Investigate repair quality control processes</li><li>Review pricing transparency with finance team</li></ul></div></div><div class=\"footer\"><p><strong>Automated Weekly Report</strong></p><p>{{ new Date().toLocaleDateString() }}</p></div></div></body></html>",
        "options": {}
      },
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        912,
        -96
      ],
      "id": "3b87cfd8-d5c3-4e8b-9b9f-dafb5b7e78ce",
      "name": "Send Weekly Summary Email",
      "webhookId": "cdd55b67-7b39-428f-84a1-9c57abbd863f",
      "credentials": {
        "gmailOAuth2": {
          "id": "cyqCGWcggZNMcSOv",
          "name": "Gmail account"
        }
      }
    }
  ],
  "pinData": {},
  "connections": {
    "Weekly Schedule - Monday 9 AM": {
      "main": [
        [
          {
            "node": "Scrape Dealership Reviews",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scrape Dealership Reviews": {
      "main": [
        [
          {
            "node": "Get Dataset Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Dataset Items": {
      "main": [
        [
          {
            "node": "Filter 1-2 Star Reviews",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter 1-2 Star Reviews": {
      "main": [
        [
          {
            "node": "AI: Analyze Review",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI: Analyze Review": {
      "main": [
        [
          {
            "node": "Parse AI Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Response": {
      "main": [
        [
          {
            "node": "Edit Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields": {
      "main": [
        [
          {
            "node": "Log to Google Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log to Google Sheet": {
      "main": [
        [
          {
            "node": "Aggregate Summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Summary": {
      "main": [
        [
          {
            "node": "Send Weekly Summary Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "c1ded20f-aac6-4ae2-bc01-d68532c566ee",
  "meta": {
    "templateCredsSetupCompleted": true,
    "instanceId": "3a43da28588548e21903e71cf1dc3ddd65c24bf0c62e7e4b77542ffe87ad79c6"
  },
  "id": "2iKRui0b0g3udA5m",
  "tags": []
}